// Copyright NaChuanSoftware Author(https://github.com/LiuShuKu). All Rights Reserved.

// Copyright (c)  2023 LiuShuKu
// Project Name :   balance
// Author       :   liushuku@yeah.net

// Package tron .
package tron

import (
	"context"
	"encoding/hex"
	"fmt"
	"github.com/btcsuite/btcd/btcec/v2"
	addr "github.com/fbsobreira/gotron-sdk/pkg/address"
	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gcache"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/qiniu/qmgo"
	"strings"
	"tronServer/internal/consts"
	"tronServer/internal/model/domain"
	"tronServer/internal/model/domain/bson"
	"tronServer/internal/service"
	"tronServer/utility/mongo"
	"tronServer/utility/tron"
)

type sTron struct {
}

func init() {
	service.RegisterTron(New())
}

func New() service.ITron {
	return &sTron{}
}

// GetUsdtBalance 获取USDT余额
func (s *sTron) GetUsdtBalance(ctx context.Context, trc20Address string) (err error) {
	// 检查 trc20地址
	if err = tron.Tron.CheckTrc20Address(ctx, trc20Address); err != nil {
		return
	}

	return err
}

// GetTrxBalance 获取Trx余额
func (s *sTron) GetTrxBalance(ctx context.Context, trc20Address string) (err error) {
	// 检查 trc20地址
	if err = tron.Tron.CheckTrc20Address(ctx, trc20Address); err != nil {
		return
	}

	return err
}

// GenTrc20 生成trc20地址
func (s *sTron) GenTrc20(ctx context.Context) (detail *domain.Trc20Detail, err error) {
	privateKey, err := btcec.NewPrivateKey()
	if err != nil {
		return
	}
	{
		if len(privateKey.Serialize()) != 32 {
			for {
				privateKey, err = btcec.NewPrivateKey()
				if err != nil {
					continue
				}
				if len(privateKey.Serialize()) == 32 {
					break
				}
			}
		}
	}
	detail = &domain.Trc20Detail{}
	{
		detail.Address = addr.PubkeyToAddress(privateKey.ToECDSA().PublicKey).String()
		detail.PrivateKey = hex.EncodeToString(privateKey.Serialize())
	}
	return
}

// DisposeUsdtTransactionRecords 处理USDT交易记录
func (s *sTron) DisposeUsdtTransactionRecords(ctx context.Context, address string) (err error) {
	var (
		details    *domain.UsdtTransactionDetailListData
		returnData []*bson.UsdtTransactionDetails
	)
	// 获取USDT交易记录
	{
		if details, err = tron.Query.GetUsdtTransactionDetails(ctx, address); err != nil {
			return
		}
	}
	// 向数据库保存
	{
		if details != nil {
			returnData, _ = s.SaveUsdtTransactionRecords(ctx, details)
		}
	}
	// 发送通知
	{
		if returnData != nil {
			go func() {
				s.NotificationAddress(ctx, returnData)
			}()
		}
	}
	return
}

// SaveUsdtTransactionRecords 保存USDT交易记录
func (s *sTron) SaveUsdtTransactionRecords(ctx context.Context, details *domain.UsdtTransactionDetailListData) (transactionDetails []*bson.UsdtTransactionDetails, err error) {
	var (
		cli      *qmgo.QmgoClient
		dataList []*bson.UsdtTransactionDetails
	)
	// 获取数据库连接
	if cli, err = mongo.Client.NewClient(ctx); err != nil {
		return
	}
	// 解析数据
	{
		if err = gconv.Structs(details.TokenTransfers, &dataList); err != nil {
			g.Log().Errorf(ctx, "Mongo Bson 解析数据失败: %s", err.Error())
			return
		}
	}
	for _, data := range dataList {
		_, err = cli.InsertOne(ctx, data)
		if err != nil {
			if !strings.Contains(err.Error(), "E11000 duplicate key") {
				g.Log().Error(ctx, err.Error())
			}
			return
		}
		transactionDetails = append(transactionDetails, data)
	}
	return
}

// NotificationAddress 通知地址
func (s *sTron) NotificationAddress(ctx context.Context, transactionDetails []*bson.UsdtTransactionDetails) {
	if nil == transactionDetails {
		return
	}
	var (
		notificationAddressList []string
		err                     error
	)
	// 获取通知地址
	if notificationAddressList, err = s.GetNotificationAddressList(ctx); err != nil {
		g.Log().Errorf(ctx, "获取通知地址失败: %s", err.Error())
		return
	}
	for _, notificationAddress := range notificationAddressList {
		for _, detail := range transactionDetails {
			data := gjson.New(detail)
			sign := gmd5.MustEncrypt(fmt.Sprintf("%s%s", data.Get("block_ts").String(), "990927"))
			sign = "$." + sign
			if _, err = g.Client().SetHeader("sign", strings.ToLower(sign)).Post(ctx, notificationAddress, data.MustToJsonString()); err != nil {
				g.Log().Errorf(ctx, "通知发送失败: %s", err.Error())
				return
			}
		}
	}
}

// GetNotificationAddressList 获取通知地址列表
func (s *sTron) GetNotificationAddressList(ctx context.Context) (notificationAddressList []string, err error) {
	var (
		data *g.Var
	)
	{
		if data, err = gcache.Get(ctx, consts.NotificationAddressKey); err != nil {
			g.Log().Errorf(ctx, "获取通知地址失败: %s", err.Error())
			return
		}
	}
	notificationAddressList = data.Strings()
	return
}
